/*
 * SPDX-License-Identifier: GPL-2.0
 * RPMB 安全协议接口定义
 * 衍生自 mmc-utils 项目，遵循 GPLv2 协议。
 */

/**
 * @file rpmb_ctl.h
 * @author Skyline
 * @version v1.0
 * @date 2025-4-23
 * @brief 该头文件定义了操作 eMMC RPMB 区的接口结构体和函数 & SHA 加密算法接口。
 */

#ifndef __RPMB_CTL_H__
#define __RPMB_CTL_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>

/**
 * @struct wr_key_opt
 * @brief 密钥操作数据结构体
 */
struct wr_key_opt {
    /**
     * @brief RPMB 设备的路径，例如 "/dev/mmcblk0rpmb"。
     */
    char *p_dev;
    /**
     * @brief 待设置的密钥，长度必须为 32 字节。
     */
    char key[32];
};

/**
 * @struct wr_opt
 * @brief 用于写入数据到 eMMC RPMB 区的操作选项结构体。
 */
struct wr_opt {
    /**
     * @brief RPMB 设备的路径，例如 "/dev/mmcblk0rpmb"。
     */
    char *p_dev;
    /**
     * @brief 要写入数据的 RPMB 区的地址。
     */
    unsigned short addr;
    /**
     * @brief 用于 RPMB 操作的密钥，长度必须为 32 字节。
     */
    char rpmb_key[32]; 
    /**
     * @brief 指向要写入的数据的指针。
     */
    char *p_in;
    /**
     * @brief 要写入的数据的长度。
     */
    unsigned int in_len;
};

/**
 * @struct rd_opt
 * @brief 用于从 eMMC RPMB 区读取数据的操作选项结构体。
 */
struct rd_opt {
    /**
     * @brief RPMB 设备的路径，例如 "/dev/mmcblk0rpmb"。
     */
    char *p_dev;
    /**
     * @brief 要读取数据的 RPMB 区的起始地址。
     */
    unsigned short addr;
    /**
     * @brief 要读取的数据块数量。
     */
    unsigned int block_num;
    /**
     * @brief 指向用于存储读取数据的缓冲区的指针。
     */
    char *p_out;
    /**
     * @brief 输出缓冲区的大小，用于确保不会发生缓冲区溢出。
     */
    unsigned int outbuf_size;
};

/**
 * @brief 检查指定 RPMB 设备的密钥状态。
 *
 * 该函数用于检查指定 RPMB 设备的密钥是否存在。
 *
 * @param p_dev 指向 RPMB 设备路径的指针，例如 "/dev/mmcblk0rpmb"。
 * @param is_exist 指向一个整数的指针，用于存储密钥是否存在的结果。
 *                 如果密钥存在，*is_exist 将被设置为非零值；否则为 0。
 * @return 操作结果，0 表示成功，非 0 表示失败。
 */
int opt_check_keystat(char *p_dev, int *is_exist);

/**
 * @brief 写入密钥到指定设备
 * 
 * @param p_dat 包含目标设备和密钥数据的结构体指针
 * @return int 执行结果状态码：
 *             - 0 成功
 *             - -1 失败
 * @warning 此函数会访问内核空间，调用前需确保参数合法性
 * @note 典型用法：
 * @code
 * struct wr_key_opt opt = {
 *     .p_dev = "/dev/crypto",
 *     .key = "1a2b3c4d..."
 * };
 * int ret = opt_write_key(&opt);
 * @endcode
 */
int opt_write_key(struct wr_key_opt *p_dat);

/**
 * @brief 向 eMMC RPMB 区写入数据。
 *
 * 该函数根据提供的写入操作选项结构体，将数据写入到指定的 RPMB 设备的指定地址。
 *
 * @param p_dat 指向 wr_opt 结构体的指针，包含写入操作所需的参数。
 * @return 操作结果，0 表示成功，非 0 表示失败。
 */
int opt_write_dat(struct wr_opt *p_dat);

/**
 * @brief 从 eMMC RPMB 区读取数据。
 *
 * 该函数根据提供的读取操作选项结构体，从指定的 RPMB 设备的指定地址读取指定数量的数据块。
 *
 * @param p_dat 指向 rd_opt 结构体的指针，包含读取操作所需的参数。
 * @return 操作结果，0 表示成功，非 0 表示失败。
 */
int opt_read_dat(struct rd_opt *p_dat);

/**
 * @brief 使用 SHA 算法对消息进行哈希计算
 * 
 * @param[in] type     指定 SHA 算法类型，可选值：
 *                     - 224: SHA-224
 *                     - 256: SHA-256
 *                     - 384: SHA-384
 *                     - 512: SHA-512
 *                     - other: SHA-512
 * @param[in] message  输入消息的指针，不可为 NULL
 * @param[in] len      输入消息的长度（字节数）
 * @param[out] digest  存放哈希结果的缓冲区指针，缓冲区大小必须满足：
 *                     - SHA-224: 至少 28 字节
 *                     - SHA-256: 至少 32 字节
 *                     - SHA-384: 至少 48 字节
 *                     - SHA-512: 至少 64 字节
 * 
 * @return 无
 * 
 * @note 
 * - 该函数不负责内存分配，调用者需确保 digest 缓冲区足够大
 * - 对于无效的 type 参数，函数将不执行任何操作
 * - 典型用法示例：
 *   @code
 *   unsigned char hash[32];
 *   sha_encryption_algorithm(256, "hello", 5, hash);
 *   @endcode
 * 
 * @warning 
 * - 如果 message 或 digest 为 NULL，将导致未定义行为
 * - 此函数不适用于密码学安全场景（如需安全哈希应使用 HMAC-SHA）
 */
void sha_encryption_algorithm(int type, const unsigned char *message, unsigned int len, unsigned char *digest);

#ifdef __cplusplus
}
#endif

#endif /* __RPMB_CTL_H__ */

